package nl.haemers.data.reflection 
{
	import flash.utils.Dictionary;
	import flash.utils.getDefinitionByName;
	import nl.haemers.data.constants.DataTypes;
	import nl.haemers.data.constants.ReflectionConstants;
	import nl.haemers.data.reflection.Type;
	import nl.haemers.data.serializers.ObjectSerializer;
	import nl.haemers.data.utils.ObjectUtils;
	/**
	 * ...
	 * @author Jonathan Haemers
	 */
	public class Property implements IProperty
	{
		protected var _name					:String;
		protected var _propertyName			:String;
		
		protected var _dataType				:String;
		protected var _xmlDataType			:String;
		
		protected var _metadatas			:IMetadatas;
		
		protected var _hasSerialize			:Boolean;
		protected var _objectType			:Type;
		protected var _ignore				:Boolean;
		protected var _overwriteable		:Boolean;
		
		public function Property(description:XML)
		{
			init(description);
		}
		
		/** Public methods **/
		/**
		 * @inheritDoc
		 */
		public function hasSerialize() : Boolean
		{
			return _hasSerialize;
		}
		/**
		 * @inheritDoc
		 */
		public function toString() : String
		{
			return _name;
		}
		
		/** Getters & Setters **/
		/**
		 * @inheritDoc
		 */
		public function get name() : String
		{
			return _name;
		}
		/**
		 * @inheritDoc
		 */
		public function get propertyName() : String
		{
			return _propertyName;
		}
		/**
		 * @inheritDoc
		 */
		public function get dataType() : String 
		{
			return _dataType;
		}
		/**
		 * @inheritDoc
		 */
		//public function get xmlDataType() : String
		//{
			//return _xmlDataType;
		//}
		
		/**
		 * @inheritDoc
		 */
		public function get metadatas() : IMetadatas
		{
			return _metadatas;
		}
		/**
		 * @inheritDoc
		 */
		public function get objectType() : Type
		{
			if(_objectType == null && !ObjectUtils.isDataType(_dataType))
			{
				_objectType = _xmlDataType ? createType(_xmlDataType) : createType(_dataType);
			}

			return _objectType;
		}
		/**
		 * @inheritDoc
		 */
		public function get ignore() : Boolean 
		{
			return _ignore;
		}
		/**
		 * @inheritDoc
		 */
		public function get overwriteable() : Boolean
		{
			return _overwriteable;
		}
		
		/**
		 * Needs to be implemented by subClasses
		 */
		public function get writeable() : Boolean
		{
			throw new Error("A Property is a generic class and should be extended.");
			return null;
		}
		
		/** Protected methods **/
		/**
		 * Create a new Type from a String.
		 * @param	type
		 * @return 
		 */
		protected function createType(type:String) : Type
		{
			var classRef:Class = getDefinitionByName(type) as Class;
			return ObjectSerializer.getType(classRef);
		}
		
		/** Private methods **/
		private function init(xml:XML):void 
		{
			_metadatas = new Metadatas(xml);
			var serialize:IMetadata = _metadatas.getMetadata(ReflectionConstants.OBJECT_ATTRIBUTE);
			_hasSerialize = serialize != null;
			
			_name = xml.@name;
			if (_hasSerialize)
			{
				if (serialize.args.hasArg(ReflectionConstants.ATTRIBUTE_NAME))
					_name = serialize.args.getArg(ReflectionConstants.ATTRIBUTE_NAME).value;
					
				if (serialize.args.hasArg(ReflectionConstants.ATTRIBUTE_IGNORE))
					_ignore = serialize.args.getArg(ReflectionConstants.ATTRIBUTE_IGNORE).value === "true";
					
				if (serialize.args.hasArg(ReflectionConstants.OVERWRITEABLE))
					_overwriteable = serialize.args.getArg(ReflectionConstants.OVERWRITEABLE).value === "true";
			}
			
			_propertyName = xml.@name;
			
			_dataType = xml.@type;
			
			if (ObjectUtils.isVector(dataType) || ObjectUtils.isDictionary(dataType))
			{
				_xmlDataType = _dataType;
				_dataType = ObjectUtils.isVector(dataType) ? DataTypes.VECTOR : DataTypes.DICTIONARY;
			}
		}
	}

}